return true;
}
+
+ /**
+ * Call refreshCounts() if there are no entries in the categorylinks table
+ * or if the category table has a row that states that there are no entries
+ *
+ * Due to lock errors or other failures, the precomputed counts can get out of sync,
+ * making it hard to know when to delete the category row without checking the
+ * categorylinks table.
+ *
+ * @return bool Whether links were refreshed
+ * @since 1.32
+ */
+ public function refreshCountsIfEmpty() {
+ $dbw = wfGetDB( DB_MASTER );
+
+ $hasLink = $dbw->selectField(
+ 'categorylinks',
+ '1',
+ [ 'cl_to' => $this->getName() ],
+ __METHOD__
+ );
+ if ( !$hasLink ) {
+ $this->refreshCounts(); // delete any category table entry
+
+ return true;
+ }
+
+ $hasBadRow = $dbw->selectField(
+ 'category',
+ '1',
+ [ 'cat_title' => $this->getName(), 'cat_pages <= 0' ],
+ __METHOD__
+ );
+ if ( $hasBadRow ) {
+ $this->refreshCounts(); // clean up this row
+
+ return true;
+ }
+
+ return false;
+ }
}
if ( $title->getNamespace() === NS_CATEGORY ) {
// T166757: do the update after the main job DB commit
DeferredUpdates::addCallableUpdate( function () use ( $title ) {
- $this->refreshCategoryIfEmpty( $title );
+ $cat = Category::newFromName( $title->getDBkey() );
+ $cat->refreshCountsIfEmpty();
} );
}
ScopedCallback::consume( $scopedLock );
}
- /**
- * @param Title $title
- */
- private function refreshCategoryIfEmpty( Title $title ) {
- $dbw = $this->getDB();
-
- $row = $dbw->selectRow(
- 'category',
- [ 'cat_id', 'cat_title', 'cat_pages', 'cat_subcats', 'cat_files' ],
- [ 'cat_title' => $title->getDBkey(), 'cat_pages <= 100' ],
- __METHOD__
- );
-
- if ( !$row ) {
- return; // nothing to delete
- }
-
- $cat = Category::newFromRow( $row, $title );
- $hasLink = $dbw->selectField(
- 'categorylinks',
- '1',
- [ 'cl_to' => $title->getDBkey() ],
- __METHOD__
- );
- if ( !$hasLink ) {
- $cat->refreshCounts(); // delete the category table entry
- }
- }
-
private function batchDeleteByPK( $table, array $conds, array $pk, $bSize ) {
$services = MediaWikiServices::getInstance();
$lbFactory = $services->getDBLoadBalancerFactory();
foreach ( $deleted as $catName ) {
$cat = Category::newFromName( $catName );
Hooks::run( 'CategoryAfterPageRemoved', [ $cat, $this, $id ] );
- }
-
- // Refresh counts on categories that should be empty now
- if ( count( $deleted ) ) {
- $rows = $dbw->select(
- 'category',
- [ 'cat_id', 'cat_title', 'cat_pages', 'cat_subcats', 'cat_files' ],
- [ 'cat_title' => $deleted, 'cat_pages <= 100' ],
- __METHOD__
- );
- foreach ( $rows as $row ) {
- $cat = Category::newFromRow( $row );
- // T166757: do the update after this DB commit
- DeferredUpdates::addCallableUpdate( function () use ( $cat ) {
- $cat->refreshCounts();
- } );
- }
+ // Refresh counts on categories that should be empty now (after commit, T166757)
+ DeferredUpdates::addCallableUpdate( function () use ( $cat ) {
+ $cat->refreshCountsIfEmpty();
+ } );
}
}